Atsibodo JavaScript „Date“? Atraskite naują „Temporal“ API ir polyfill. Valdykite datas, laikus ir laiko juostas tiksliai bei lengvai bet kurioje programoje.
Daugiau nei Data: Įvaldykite JavaScript ateitį su „Temporal Polyfill“
Dešimtmečius viso pasaulio kūrėjai susidūrė su bendra problema: JavaScript Date objektu. Jis buvo nesuskaičiuojamų klaidų, vėlyvų derinimo sesijų ir internacionalizacijos galvos skausmų šaltinis. Jo kintanti prigimtis, painus API ir liūdnai pagarsėjęs prastas laiko juostų palaikymas padarė patikimą datų ir laiko logiką dideliu iššūkiu. Tačiau ši era pagaliau baigiasi.
Pristatome Temporal API – modernų, išsamų ir puikiai suprojektuotą pasiūlymą, skirtą revoliucijonuoti datų ir laiko tvarkymą JavaScript kalboje. Jis kūrėjams siūlo nekintamą, aiškų ir galingą įrankių rinkinį. Vienintelis minusas? Jis dar nepasiekiamas visose naršyklėse ir JavaScript vykdymo aplinkose. Štai kur atsiranda Temporal Polyfill. Tai tiltas į ateitį, leidžiantis jums rašyti švarų, patikimą ir ateičiai atsparų datų / laiko kodą šiandien. Šis vadovas nuodugniai paaiškins, kodėl turite palikti senąjį Date objektą ir kaip įvaldyti „Temporal Polyfill“ savo globalioms programoms.
Kodėl turime atsisakyti JavaScript `Date` objekto
Prieš nagrinėjant sprendimą, labai svarbu suprasti problemos gilumą. Jei dirbote su JavaScript pakankamai ilgai, tikriausiai susidūrėte su šiomis problemomis:
- Kintamumo beprotybė:
Dateobjektas yra kintamas. Kai perduodateDateobjektą funkcijai, ta funkcija gali pakeisti jo reikšmę, o tai sukelia nenuspėjamą šalutinį poveikį ir klaidas, kurias neįtikėtinai sunku atsekti. Įsivaizduokite, kad funkcija, apskaičiuojanti būsimą datą, atsitiktinai modifikuoja pradinę pradžios datą, naudojamą kitur jūsų programoje. - Painus ir nenuoseklus API: API yra pilnas keistenybių.
getMonth()grąžina reikšmę nuo 0 (sausis) iki 11 (gruodis), ogetDate()– nuo 1 iki 31. Šis nenuoseklumas suklaidino ne vieną kūrėjų kartą. Metodai, tokie kaipgetYear(), jau seniai nebenaudojami ir sukelia dar daugiau painiavos. - Laiko juostų košmaras: Tai, ko gero, didžiausias skausmo taškas globalioms programoms.
Dateobjektas yra pagrįstas vartotojo sistemos laiku. Skaičiavimai tarp skirtingų laiko juostų yra sudėtingi, linkę į klaidas ir dažnai reikalauja sunkiasvorių trečiųjų šalių bibliotekų. Paprasti klausimai, pavyzdžiui, "Kiek valandų bus Tokijuje, kai Niujorke bus 9:00 val. ryto?" tampa dideliu iššūkiu. - Vienas dydis netinka niekam:
Dateobjektas visada atspindi konkretų laiko momentą (laiko žymę). Nėra švaraus būdo atvaizduoti tik datą (pvz., gimtadienį, '2023-10-26') ar tik laiką (pvz., kasdienį žadintuvą, '08:30:00'). Tai verčia kūrėjus valdyti ir ignoruoti nereikšmingus laiko ar datos komponentus, pridedant nereikalingo sudėtingumo.
Žvilgsnis į ateitį: „Temporal“ API
„Temporal API“ nuo pat pradžių buvo sukurtas TC39 komiteto (įstaigos, standartizuojančios JavaScript) visoms šioms problemoms išspręsti. Jis sukurtas remiantis keliais pagrindiniais principais, dėl kurių su juo dirbti yra malonumas:
- Nekintamumas: Kiekvienas „Temporal“ objektas yra nekintamas. Atlikus operaciją, pvz., pridėjus 5 dienas prie datos, originalus objektas nepakinta. Vietoj to, jis grąžina naują „Temporal“ objektą su atnaujinta reikšme. Tai pašalina didelę klaidų kategoriją.
- Aiškus ir nedviprasmiškas API: API sukurtas taip, kad būtų aiškus ir nuspėjamas. Metodai pavadinti prasmingai (pvz.,
dayOfWeekvietojgetDay), o mėnesiai skaičiuojami nuo 1 (1 – sausis). Tai, ką matote, yra tai, ką gaunate. - Pirminis laiko juostų ir kalendoriaus palaikymas: Laiko juostos nėra pamiršta smulkmena; jos yra pagrindinė funkcija. Galite lengvai kurti datas konkrečiose laiko juostose, konvertuoti tarp jų ir patikimai tvarkyti sudėtingas problemas, tokias kaip vasaros laikas (DST). Jis taip pat apima negregorijaus kalendorių palaikymą.
- Turtingas tipų rinkinys kiekvienam poreikiui: Vietoj vieno monolitinio objekto, „Temporal“ teikia daugybę specializuotų objektų skirtingiems naudojimo atvejams, todėl jūsų kodas tampa išraiškingesnis ir tikslesnis.
Jungiantis šiandieną ir rytojų: Kas yra „Temporal Polyfill“?
Polifilas (terminas, kilęs iš glaisto prekės ženklo „Polyfilla“) yra kodo dalis, kuri suteikia modernias funkcijas senesnėse aplinkose, kurios natūraliai jų nepalaiko. Jis užpildo naršyklės arba vykdymo aplinkos trūkumus įgyvendinant žiniatinklio standartus.
„Temporal API“ yra naujas standartas. Nors jis yra 4-ajame etape (galutiniame etape) TC39 procese, naršyklių tiekėjams ir „Node.js“ prižiūrėtojams reikia laiko, kad jį įdiegtų. Temporal Polyfill (@js-temporal/polyfill) yra aukštos kokybės, bendruomenės palaikoma biblioteka, kuri JavaScript kalba įgyvendina visą „Temporal API“ specifikaciją. Įtraukdami ją į savo projektą, galite naudoti globalų Temporal objektą ir visus jo metodus taip, tarsi jie jau būtų integruoti į aplinką. Kai naršyklės galiausiai išleis vietinį palaikymą, jūsų kodas ir toliau veiks sklandžiai, dažnai su našumo padidėjimu.
Projekto nustatymas su „Temporal Polyfill“
Pradėti yra paprasta. Galite pridėti polyfill prie savo projekto naudodami mėgstamą paketų tvarkyklę.
Įdiegimas naudojant paketų tvarkyklę
Projektams, naudojantiems Node.js, arba priekinės sąsajos projektams su kūrimo etapu (pvz., naudojantiems Webpack, Vite arba Parcel), atidarykite terminalą ir paleiskite:
npm:
npm install @js-temporal/polyfill
yarn:
yarn add @js-temporal/polyfill
pnpm:
pnpm add @js-temporal/polyfill
Importavimas į jūsų projektą
Įdiegus, jums tereikia importuoti jį vieną kartą programos įvesties taške (pvz., pagrindiniame index.js arba main.ts faile). Tai padarys Temporal objektą prieinamą globaliai.
// Import the polyfill at the top of your main application file
import { Temporal } from '@js-temporal/polyfill';
// Now you can use Temporal anywhere in your app!
const now = Temporal.Now.plainDateTimeISO();
console.log(now.toString());
Naudojimas CDN naršyklėje
Paprastiems tinklalapiams, demonstracijoms ar internetiniams kodo redaktoriams, tokiems kaip CodePen, galite įtraukti polyfill tiesiogiai naudodami CDN scenarijaus žymę savo HTML faile. Padėkite ją prieš savo scenarijus, kurie naudoja `Temporal`.
<!DOCTYPE html>
<html>
<head>
<title>Temporal Polyfill Demo</title>
<!-- Load the polyfill from a CDN -->
<script src="https://cdn.jsdelivr.net/npm/@js-temporal/polyfill/dist/index.umd.js"></script>
</head>
<body>
<script>
// The Temporal object is now available globally
const today = Temporal.Now.plainDateISO();
console.log(`Today's date is ${today.toString()}`);
document.body.innerText = `Today's date is ${today.toString()}`;
</script>
</body>
</html>
Praktinė „Temporal“ objektų apžvalga (su polyfill pavyzdžiais)
Panagrinėkime pagrindinius „Temporal“ teikiamus objektus. Jų supratimas leis patenkinti 99% jūsų datų / laiko manipuliavimo poreikių.
`Temporal.PlainDate`: Gimtadieniams, šventėms ir sukaktims
Šis objektas atspindi kalendorinę datą be jokios laiko ar laiko juostos informacijos. Jis puikiai tinka, kai jums rūpi tik metai, mėnuo ir diena.
// Creating a PlainDate (year, month, day)
const releaseDate = new Temporal.PlainDate(2025, 7, 18);
console.log(releaseDate.toString()); // "2025-07-18"
// Getting components (months are 1-based!)
console.log(releaseDate.year); // 2025
console.log(releaseDate.month); // 7
console.log(releaseDate.day); // 18
console.log(releaseDate.dayOfWeek); // 5 (Friday)
// Immutability in action: adding days returns a NEW object
const oneWeekLater = releaseDate.add({ days: 7 });
console.log(releaseDate.toString()); // "2025-07-18" (original is unchanged)
console.log(oneWeekLater.toString()); // "2025-07-25"
`Temporal.PlainTime`: Kasdieniams žadintuvams ir darbo valandoms
Tai atspindi „sieninio laikrodžio“ laiką be datos ar laiko juostos. Pagalvokite apie darbo valandas ar pasikartojantį žadintuvą.
// Creating a PlainTime (hour, minute, second)
const openingTime = new Temporal.PlainTime(9, 0, 0);
console.log(openingTime.toString()); // "09:00:00"
const closingTime = Temporal.PlainTime.from('17:30');
console.log(closingTime.toString()); // "17:30:00"
// Comparing times
const appointmentTime = new Temporal.PlainTime(10, 15);
console.log(Temporal.PlainTime.compare(appointmentTime, openingTime)); // 1 (appointment is later)
`Temporal.PlainDateTime`: Vietiniams susitikimams be laiko juostos dviprasmybių
Tai sujungia `PlainDate` ir `PlainTime`. Jis atspindi konkrečią datą ir laiką, bet vis dar yra atsietas nuo laiko juostos. Tai idealiai tinka planuojant vietinį dantisto susitikimą, kur laiko juosta yra numanoma.
const localAppointment = new Temporal.PlainDateTime(2024, 12, 10, 14, 30);
console.log(localAppointment.toString()); // "2024-12-10T14:30:00"
// You can add durations
const oneHourLater = localAppointment.add({ hours: 1 });
console.log(oneHourLater.toString()); // "2024-12-10T15:30:00"
`Temporal.ZonedDateTime`: Globalių programų herojus
Tai yra galingiausias tipas tarptautinėms programoms. Jis atspindi tikslų laiko momentą konkrečioje laiko juostoje. Jis supranta vasaros laiką ir gali būti tiksliai konvertuojamas į bet kurią kitą laiko juostą.
// Creating a ZonedDateTime for an event in Tokyo
// Time zones use IANA identifiers (e.g., 'Asia/Tokyo', 'Europe/London')
const tokyoLaunch = new Temporal.ZonedDateTime(
978307200000000000n, // Nanoseconds since Unix epoch
'Asia/Tokyo'
);
console.log(tokyoLaunch.toString()); // "2001-01-01T09:00:00+09:00[Asia/Tokyo]"
// Find out what time that is for someone in New York
const newYorkTime = tokyoLaunch.withTimeZone('America/New_York');
console.log(newYorkTime.toString()); // "2000-12-31T19:00:00-05:00[America/New_York]"
// Getting the current time in a specific time zone
const nowInDubai = Temporal.Now.zonedDateTimeISO('Asia/Dubai');
console.log(`Current time in Dubai: ${nowInDubai.toPlainTime()}`);
`Temporal.Instant`: Universalus, mašinai patogus laiko žymeklis
„Instant“ atspindi vieną, tikslų tašką globalioje laiko juostoje, nepriklausomą nuo jokio kalendoriaus ar laiko juostos. Jis matuojamas nanosekundėmis nuo „Unix epoch“ ir visada yra UTC. Jis puikiai tinka serverio žurnalams, API laiko žymėms ir duomenų bazės įrašams.
// Get the current exact moment in time
const now = Temporal.Now.instant();
console.log(now.toString()); // e.g., "2023-10-26T14:45:12.123456789Z"
// Comparing instants is simple and reliable
const later = now.add({ seconds: 30 });
console.log(Temporal.Instant.compare(now, later)); // -1 (now is earlier)
`Temporal.Duration`: Aiškus laiko tarpų skaičiavimas
„Duration“ objektas atspindi laiko trukmę, pvz., "3 mėnesiai, 2 savaitės ir 5 valandos". Tai neįtikėtinai naudinga skaičiavimams.
// Create a duration
const projectDuration = Temporal.Duration.from({ weeks: 6, days: 3 });
console.log(projectDuration.toString()); // "P6W3D"
const startDate = new Temporal.PlainDate(2024, 1, 15);
// Add the duration to a date
const deadline = startDate.add(projectDuration);
console.log(deadline.toString()); // "2024-02-29"
// Calculate the difference between two dates
const date1 = new Temporal.PlainDate(1999, 8, 24);
const date2 = new Temporal.PlainDate(2023, 10, 26);
const difference = date2.since(date1);
console.log(difference.toString()); // "P24Y2M2D" (24 years, 2 months, 2 days)
console.log(`Years: ${difference.years}, Months: ${difference.months}, Days: ${difference.days}`);
Realių iššūkių sprendimas naudojant „Temporal Polyfill“
Pažiūrėkime, kaip šie objektai sprendžia įprastas, praktines problemas.
Naudojimo atvejis: Globalaus internetinio seminaro tvarkaraščio kūrimas
Problema: Jūs planuojate internetinį seminarą 15:00 UTC laiku. Jums reikia parodyti kiekvienam vartotojui pradžios laiką jo vietinėje laiko juostoje ir atgalinį skaičiavimą.
Sprendimas naudojant `Temporal.ZonedDateTime`:
// 1. Define the event time in UTC
const webinarInstant = Temporal.Instant.from('2025-03-15T15:00:00Z');
// 2. Get the user's time zone (in a real app, from the browser or user profile)
const userTimeZone = 'Europe/Berlin'; // Example
// 3. Convert the webinar time to the user's time zone
const webinarInUserZone = webinarInstant.toZonedDateTimeISO(userTimeZone);
console.log(`Webinar starts at: ${webinarInUserZone.toPlainTime()} in your time zone.`);
// Output: "Webinar starts at: 16:00:00 in your time zone." (Berlin is UTC+1 in March)
// 4. Create a countdown
function updateCountdown() {
const now = Temporal.Now.instant();
const timeRemaining = webinarInstant.since(now, { largestUnit: 'day' });
console.log(`Time remaining: ${timeRemaining.days} days, ${timeRemaining.hours} hours, ${timeRemaining.minutes} minutes.`);
}
// Call updateCountdown() periodically
setInterval(updateCountdown, 1000);
Naudojimo atvejis: Tikslūs amžiaus ir sukakčių skaičiavimai
Problema: Tiksliai apskaičiuoti kažkieno amžių arba įvykio trukmę su „Date“ objektu yra sudėtinga dėl keliamųjų metų ir laiko komponentų.
Sprendimas naudojant `Temporal.PlainDate`:
const birthDate = Temporal.PlainDate.from('1990-06-25');
const today = Temporal.Now.plainDateISO();
const age = today.since(birthDate, { largestUnit: 'year' });
console.log(`You are ${age.years} years, ${age.months} months, and ${age.days} days old.`);
Naudojimo atvejis: Prenumeratos atsiskaitymo ciklų valdymas
Problema: Pridėjus „vieną mėnesį“ prie datos, tokios kaip sausio 31 d., gali būti dviprasmiška. Ar ji taps vasario 28 d. (arba 29 d.)? Senasis `Date` objektas dažnai persikeldavo į kovo mėnesį.
Sprendimas naudojant `Temporal.PlainDate` ir parinktis:
const subscriptionStart = Temporal.PlainDate.from('2024-01-31');
// Add one month. Temporal handles the leap year logic correctly.
const nextBillingDate = subscriptionStart.add({ months: 1 });
console.log(nextBillingDate.toString()); // "2024-02-29" (since 2024 is a leap year)
const anotherStart = Temporal.PlainDate.from('2023-01-31');
const nextBillingForNonLeap = anotherStart.add({ months: 1 });
console.log(nextBillingForNonLeap.toString()); // "2023-02-28"
Našumas, paketo dydis ir pasirengimas gamybai
Svarbu būti praktiškiems. Pridėjus bet kokį „polyfill“ padidėja jūsų programos paketo dydis. @js-temporal/polyfill yra išsamus, ir 2023 m. pabaigoje jis jūsų paketui prideda apie 20-30 kB (suglaudintų). Nors tai nėra nereikšminga, turėtumėte palyginti tai su alternatyvomis:
- Naudojant sunkią, trečiųjų šalių datų biblioteką, tokią kaip Moment.js (dabar jau palikimo projektas) arba date-fns. „Temporal polyfill“ dažnai yra panašaus dydžio, tačiau turi pagrindinį privalumą – tai yra ateities standartas.
- Rašant sudėtingą, klaidoms jautrią rankinę datų logiką. Kūrėjo laiko ir galimų klaidų kaina dažnai gerokai viršija kelių kilobaitų polyfill kainą.
Ar jis paruoštas gamybai? Taip. Polifilas yra stabilus, gerai išbandytas ir atitinka oficialią specifikaciją. Naudodami jį, investuojate į ateičiai atsparų kodą.
Kelias į priekį: Nuo „Polyfill“ iki vietinio įdiegimo
„Temporal API“ pasiūlymas yra 4-ajame etape, o tai reiškia, kad jis yra baigtas ir paruoštas įtraukti į ECMAScript standartą. Naršyklių ir variklių kūrėjai dabar aktyviai dirba su vietiniais įdiegimais. 2023 m. pabaigos / 2024 m. pradžios duomenimis, jį galite rasti už funkcijos vėliavėlių kai kuriose naršyklėse.
Perėjimas bus sklandus. Polifilas patikrina, ar egzistuoja vietinis Temporal objektas. Jei jis egzistuoja, polifilas nieko nedaro. Jei ne, jis sukuria globalų Temporal objektą. Tai reiškia, kad kai jūsų vartotojai atnaujins savo naršykles, jūsų programa automatiškai pradės naudoti greitesnį, vietinį įdiegimą, jums nereikės keisti nė vienos kodo eilutės.
Išvada: Jūsų kitas žingsnis moderniame JavaScript
Dienos, kai tekdavo vargti su JavaScript „Date“ objektu, yra suskaičiuotos. „Temporal API“ suteikia patikimą, intuityvią ir galingą alternatyvą, kuri elegantiškai ir tiksliai sprendžia realias problemas. Priimdami Temporal Polyfill, jūs ne tik naudojate naują biblioteką; jūs apsaugote savo programas ateičiai ir suderinate savo kodą su oficialia JavaScript kalbos kryptimi.
Nesvarbu, ar kuriate paprastą planavimo įrankį, ar sudėtingą globalią platformą, aiškumas ir patikimumas, gautas naudojant „Temporal“, yra milžiniškas. Nustokite kovoti su `getMonth()`. Nustokite jaudintis dėl laiko juostų. Pradėkite rašyti švaresnį, saugesnį ir išraiškingesnį datų ir laiko kodą šiandien. Jūsų ateities „aš“ – ir jūsų tarptautiniai vartotojai – jums padėkos.